تطوير العملاء للخدمات المشتركة



$packed_address

الوصف

$sock = IO::Socket::INET->new(Proto=>'tcp');

0x07 0xC0

PERL

كلاً من بروتوكول نقل الملفات File Transfer Protocol(FTP) والتلنت لدخول عن بعد هي من البروتوكولات الإنترنت القديمة . توضح معاً كنهايتين قصوى لبروتوكلات الشبكة : جلسة FTP هي مجموعة تركيبها عالي المستوى جداً ويمكن توقع المعاملات(transactions)حيث ان المعاملة هي سلسلة منفصلة من الأعمال يجب أن تجري كلها أو لايجري أي عمل منها أبداً ، بينما جلسة التلنت هي تفاعلية عالية جداً ولايمكن توقع معاملاتها ، توفر لغة البيرل العديد من الواحدات برمجية لتعامل مع بروتوكلات التطبيق كالFTP,TELNET .


Net::FTP

هناك مجلد على خادم FTP البعيد يتغير بمرور بضعه اسابيع ، عند ذلك سوف تحتاج الى نسخة mirror من المجلد على جهازك المحلي و تحديث نسختك كلما تغير هذا المجلد ، فلا يمكنك إستخدام واحد من العديد من إسكربتات "mirror" لهذا العمل لان اسم المجلد يحتوي timestamp (التواريخ Date/Time ) وستحتاج الى عمل مطابقة نمط pattern match لتعرف على المجلد الصحيح .الوحدة البرمجية Net::FTP تعمل عملية الإنقاذ (rescue) .

وحدة Net::FTP هي جزء من مكتبة الإنترنت libnet utilities المقدمة من قبل Graham Barr . كما يوجد في المكتبة العديد من الواحدات البرمجية الاخرى التي سوف نناقشها لاحقاً ان شاء الله Net::SMTP, Net::NNTP, Net::POP3 . عند إنزال وحدات مكتبة الإنترنت libnet عادتاً مايضع أسكربت التنزيل في المحدث الإعداءات الافتراضية لعائلة وحدات Net::* كوضع FTP firewall proxy الافتراضي و default mail exchanger لمجال الخاص بك الى غير ذلك من الإعدادت .مع مشاهدة الوثيقة في Net::Config للمعلومات عن الكيفية التي تصبح override على الإعداءات الافتراضية السابقة .

Net::FTP كماهي في العديد من الواحدات العميلة (نسميها واحدات برمجية عميلة لأنها تشتغل عادة في محطة عمل مستخدم محلي وهي قادرة على الاتصال عن بعد بالخوادم التي تشتغل في كمبيوترات اخرى في اغلب الاحيان تكون خوادم مشتركة في الشبكة ) تستخدم تفاعل كائنات موجهه ، عندما تدخل الى أول ولولوج الى خادم FTP تعيد كائن Net::FTP يتم من خلاله التعامل مع الخادم كالحصول على قائمة المجلدات من الخادم ، أو أستخدام الكائن لنقل الملفات أو لإرسال أوامر اخرى .


A Net::FTP Example

يوجد أسفل مثال بسيط يستخدم Net::FTP للإتصال الى ftp.perl.org وتحميل ملف RECENT من المجلد /pub/CPAN/ . عندما ينجح الإتصال بالخادم البعيد يسترجع البرنامج الملف RECENT في المجلد الحالي للبرنامج ، يحتوي هذا الملف على أسماء كل الملفات المرفوعة حديثاً الى CPAN .

#!/usr/bin/perl -w
# file: ftp_recent.pl
# Downloading a single file with Net::FTP

use Net::FTP;

use constant HOST => 'ftp.perl.org';
use constant DIR  => '/pub/CPAN';
use constant FILE => 'RECENT';

my $ftp = Net::FTP->new(HOST) or die "Couldn't connect: $@\n";
$ftp->login('anonymous')      or die $ftp->message;
$ftp->cwd(DIR)                or die $ftp->message;
$ftp->get(FILE)               or die $ftp->message;
$ftp->quit;

warn "File retrieved successfully.\n";

السطر 1-5 : تهيئة البرنامج بشحن وحـدة Net::FTP وتعريف ثوابت المضيف للإتصال اليه و مسار الملف الذي نرغب تحميله .

السطر 6 : الأتصال الى المضيف البعيد سنتصل الى مضيف FTP بإستحضار new() طريقة وحـده Net::FTP مع أسم المضيف المراد الإتصال الية .في نجاح الاتصال تنشأ هذة الطريقة وتعيد كائناً Net::FTP متصل إلى الخادم البعيد ، في الفشل تعيد undef وينتهي die البرنامج مع رسائلة الخطأ بترك رسائلة الخطأ التشخيص في $@ .

السطر 7 : الولوج الى الخادم بعدما إتصالنا الى الخادم مازال يتوجب علينا الولوج بإستدعى login() طريقة الكائن Net::FTP مع أسم المستخدم وكلمة المرور .نشاهد إستخدام anonymous FTP للولوج مع المستخدم "anonymous" وندع Net::FTP إستكمال كلمة المرور الافتراضية الملائمة. أن نجح الولوج تعيد login() قيمة الصواب عدا ذلك تعيد عدم الصوب وتنتهي مع رسالة عن طريق إستخدام message() طريقة كائن FTP لإسترجع نص رسالة الخادم الاخير .

السطر 8 : التغير الى المجلد البعيد سوف نستحضر cwd() طريقة كائن FTP هذة الطريقة اختصار "change working directory" بمعني تغير العمل الى المجلد المرغوب الدخول اليه ، ان فشلت ينتهي البرنامج مع رسالة الخادم .

السطر 9 : إسترجاع الملف نستدعي get() طريقة كائن FTP لإستراجاع الملف المطلوب . في النجاح تنسخ Net::FTP الملف البعيد الى المحلي بنفس الاسم في المجلد الحالي ، عدا ذلك تنهي مع رسالة خطأ .

السطر 10-11 : إستدعى quit() طريقة كائن FTP وذلك لإغلاق الإتصال .

FTP and Command-Based Protocols

ان بروتوكول FTP مثال عينة مشتركة لخدمات الإنترنت :(تأكد ؟ يعتبر من البروتوكلات المستندة على الاوامر ) ال command-based protocol.هذا البروتوكول المتعارف well-defined يقيد التفاعل بين العميل والخادم في المقام الاول مع قضية العميل ذو سطر الامر الواحد ومع الخادم الذي يعيد رد السطر الموجهه line-oriented .

لكل أوامر العميل حالة غير حساسة للحروف short word يمكن ان يتبعه وسيط أو اكثر ، ينتهي الامر بزوج CRLF كما ذكرنا سابقاً في قسم ثرثرة العميل عندما استخدام اسكربت gab2.pl لتواصل مع خادم FTP ، أوامر العميل في بروتوكول FTP مثل user و PASS المستخدمة معاً للولوج الى الخادم ، الامر الاخر HELP للحصول الى معلومات الإستعمال ، و QUIT لخروج من الخادم .يوجد هناك أوامر اخرى تستخدم لإرسال وإستراجاع الملفات و الحصول على قائمة الملفات في المجلد الى غير ذلك من الاوامر المتعلقة مع بروتوكول FTP . على سبيل المثال عندما يرغب العميل الولوج الى الخادم تحت اسم المستخدم "anonymous" علية ان يرسل الامر التالي

USER anonymous

يشمل كل رد من الخادم الى العميل على سطر أو عدة أسطر CRLF-delimited .دوماً يبدأ أول سطر مع شفره النتيجة المتكونة من ثلاثة أرقام تشير الى ماهو الناتج من الامر ، يلية عادتاً رسالة نستطيع قراءتها .على سبيل المثال عندما ينجح الامر USER يعطي الخادم الرد :

331 Guest login ok, send your complete e-mail address as password.

بعض الاوقات يكون رد الخادم ممتدد في عدة أسطر ، في هذة الحالة شفرة النتيجة العددي على أول سطر منهى مع اشارة "-" وتكتب شفرة النتيجة مرة اخرى في أخر سطر (بدون علامة dash ) . رد برتوكول FTP لإمر HELP يوضح هذا :

HELP 214-The following commands are recognized (* =>'s unimplemented). USER PORT STOR MSAM* RNTO NLST MKD CDUP PASS PASV APPE MRSQ* ABOR SITE XMKD XCUP ACCT* TYPE MLFL* MRCP* DELE SYST RMD STOU SMNT* STRU MAIL* ALLO CWD STAT XRMD SIZE REIN* MODE MSND* REST XCWD HELP PWD MDTM QUIT RETR MSOM* RNFR LIST NOOP XPWD 214 Direct comments to ftp-bugs@wuarchive.wustl.edu

غالباً يحتاج التشارك بين العميل والخادم لتبادل كميات كبيرة من البيانات ليس مع الامر . لعمل ذلك يرسل العميل الامر لكي ينبه warn الخادم بأن البيانات قادمة ، ثم يرسل البيانات ، ومن ثم ينهي المعلومات بإرسال lone dot (".") على السطر ذاتة .سوف نشاهد ذلك في أمثلة الفصل القادم عند فحص التفاعل بين e-mail client و SMTP server .

شفرة نتيجة الخادم ثابتة arbitrary لكن عموماً بحسب الإتفاقية غالباً شفرات النتيجة بين 100 الى 199 مستخدم لإرسائل المعلوماتية ، وفي المدى 200–299 مستخدمة للإشارة الى استكمال نجاح الامر ، والشفره بين 300–399 تستخدم عندما يتوجب على العميل أنجاز معلومات أكثر مثل اخبار ارفاق كلمة المرور لإسم المستخدم . شفرة النتيجة من 400 فما فوق تشير الى مختلف الاخطاء اعني 400–499 تستخدم لإخطاء العميل مثل الامر غير صحيح invalid command ، بينما 500 وما فوق تستخدم لإخطاء الخادم مثل out of memory condition.

لان الاوامر المستندة على الخوادم تكون مشتركة في أغلب التطبيقات ، هكذا توفر حزمة مكتبة الانترنت libnet package وحدة برمجية معممة تسمى Net::Cmd ، هذة الوحدة البرمجية لاتعمل اي شيء بذاتها لكن تضيف اشياء وظيفية الى سلالة وحدة IO::Socket التي تمنح لهم التواصل السهل مع هذا النوع من خادم الشبكة .ولاننسى ان Net::FTP, Net::SMTP, Net::NNTP, Net::POP3 جميعها مشتقة من وحدة Net::Cmd.

تودي وحدة Net::Cmd طريقتين اساسية هم command() و response():


$success = $obj->command($command [,@args])

تعمل على ارسال الامر المشار في المتغير $command إلى الخادم ، ويلية وسيط خياري لدراج اكثر من أمر ، كما انها تضيف تلقائياً بين كل أمر بفراغ وتذيل CRLF إلى نهاية الأمر، وعندما الامر يسلم بنجاح تعيد الطريقة قيمة الصواب .


$status = $obj->response

تجلب وتعرب رد الخادم للإمر الاخير ، وتعيد الطريقة اغلب الأرقام كناتج للطريقة ،فمثلاً اذا شفرة نتيجة الخادم 331 فأن response() سوف تعيد 3 ، في الفشل تعيد غير معرف undef.

الاصناف الفرعية لوحدة Net::Cmd مبنية باكثر الطرق بساطة وارتقاء مقارناً بالطرق command() and response() .على سبيل المثال login() طريقة وحـدة Net::FTP انها تستدعي الطريقة command() مرتين ، مرة لقضية الامر USER ومرة اخرى لقضية الامر PASS .لانك لان تتمكن بشكل عادي من استدعاء الطرق command() and response() لكنك تستطيع استخدام الطرق المحدودة والمناسبة الموداءة بواسطة الاصناف الفرعية . مع ذلك فأن دوال command() and response() متوفرة للوصول الى الوظائف التي احياناً ماتحتاجها الغير موجودة في الوحـدات .

تودي وحـدة Net::Cmd ايضاً بعض الطرق المشتركة المستخدمة من قبل التطبيقات طرف العميل end-user applications. مثل code(), message(), ok():


$code = $obj->code

تعيد ثلاثة أرقام لشفرة النتيجة من الرد الاخير .

$message = $obj->message

تعيد النص لأخر رسالة من الخادم ، يفيد هذا لتعين تشخيص الاخطاء

$ok = $obj->ok

يعيد قيمة الصواب اذا اخر رد للخادم يشير الى النجاح ، وغير ذلك فهو يعيد غير الصوب . بمعنى سوف يعيد الصواب اذا شفرة النتيجة كانت أكبر من 0 لكن أقل من 400 .



The Net::FTP API

في المثال التالي نشاهد تفصيل أكثر Net::FTP API ، هذة الوحـدة البرمجية سلاسلة من وحـدات IO::Socket and Net::Cmd.كما أنها سلالة من IO::Socket يمكننا ان نستخدمها كمقبض ملف لتواصل المباشر مع الخادم .على سبيل المثال يمكن الكتابة والقراءة الى كائن Net::FTP بإستخدام الطرق مثل syswrite() و sysread() وعلى الأرجح لن ترغب في استخداها .وايضاً كما انها سلاسلة من الوحـدة البرمجية Net::Cmd هكذا Net::FTP تدعم الطرق code(), message(), and ok() .للأطلاع اكثر في وضيعة شفرة النتيجة لبروتوكول FTP في RFC 959 (في Appendix D).

هذة الوحدة Net::FTP توفر العديد من الطرق بأضافة الى عدد الطرق المتوارثة من الأباء التي تميز لتعامل مع بروتوكول FTP والتالي سرد لهذة الطرق مع تباين عملها .يمكن مشاهدت جميع الطرق المشتركة منها لوثيقة perldoc Net::FTP .


$ftp = Net::FTP->new($host [,%options])

تنشأ الطريقة كائناً Net::FTP ، يتوجب وضع الوسيط الاول $host وهو أسم المجال خادم FTP المرغوب الإتصال contact ألية .الوسيط الاخر خياري يوضع زوج key/value كما هو مشاهد يعمل على وضع خيارات للجلسة ، هذة الخيارات مشاهد في الجدول أسفل .على سبيل المثال لكي نتصل الى ftp.perl.org مع تمكين hash marks و timeout بثلاثين ثانية نستخدم العبارة التالي :

$ftp = Net::FTP('ftp.perl.org', Timeout=>30, Hash=>1);

Two of the oldest Internet protocols are the File Transfer Protocol, FTP, and Telnet, for remote login. They illustrate the two extremes of network protocols: An FTP session is a highly structured and predictable set of transactions; a Telnet session is unpredictable and highly interactive. Perl has modules that can tame them both.


Net::FTP

There's a directory on a remote FTP server that changes every few weeks. You want to mirror a copy of the directory on your local machine and update your copy every time it changes. You can't use one of the many "mirror" scripts to do this because the directory name contains a timestamp, and you need to do a pattern match to identify the right directory. Net::FTP to the rescue.

Net::FTP is part of the libnet utilities by Graham Barr. In addition to Net::FTP, libnet includes Net::SMTP, Net::NNTP, and Net::POP3 discussed in later chapters. When you install the libnet modules, the install script prompts you for various default configuration parameters used by the Net::* modules. This includes such things as an FTP firewall proxy and the default mail exchanger for your domain. See the documentation for Net::Config (also part of the libnet utilities) for information on how to override the defaults later.

Net::FTP, like many of the client modules, uses an object-oriented interface. When you first log in to an FTP server, the module returns a Net::FTP object to you. You then use this object to get directory listings from the server, to transfer files, and to send other commands.


A Net::FTP Example

Figure 6.1 is a simple example that uses Net::FTP to connect to ftp.perl.org and download the file named RECENT from the directory /pub/CPAN/. If the program runs successfully, it creates a file named RECENT in the current directory. This file contains the names of all files recently uploaded to CPAN.

Figure 6.1. Downloading a single file with Net::FTP
#!/usr/bin/perl -w
# file: ftp_recent.pl
# Downloading a single file with Net::FTP

use Net::FTP;

use constant HOST => 'ftp.perl.org';
use constant DIR  => '/pub/CPAN';
use constant FILE => 'RECENT';

my $ftp = Net::FTP->new(HOST) or die "Couldn't connect: $@\n";
$ftp->login('anonymous')      or die $ftp->message;
$ftp->cwd(DIR)                or die $ftp->message;
$ftp->get(FILE)               or die $ftp->message;
$ftp->quit;

warn "File retrieved successfully.\n";

Lines 1–5: Initialize We load the Net::FTP module and define constants for the host to connect to and the file to download.

Line 6: Connect to remote host We connect to the FTP host by invoking the Net::FTP new() method with the name of the host to connect to. If successful, new() returns a Net::FTP object connected to the remote server. Otherwise, it returns undef, and we die with an error message. In case of failure, new() leaves a diagnostic error message in $@.

Line 7: Log in to the server After connecting to the server, we still need to log in by calling the Net::FTP object's login() method with a username and password. In this case, we are using anonymous FTP, so we provide the username "anonymous" and let Net::FTP fill in a reasonable default password. If login is successful, login() returns a true value. Otherwise, it returns false and we die, using the FTP object's message() method to retrieve the text of the server's last message.

Line 8: Change to remote directory We invoke the FTP object's cwd() ("change working directory") method to enter the desired directory. If this call fails, we again die with the server's last message.

Line 9: Retrieve the file We call the FTP object's get() method to retrieve the desired file. If successful, Net::FTP copies the remote file to a local one of the same name in the current directory. Otherwise we die with an error message.

Lines 10–11: Quit We call the FTP object's quit() method to close the connection.